--local Util = require("common.Util")
local Timer = require("core.Timer")
local Obj = require("core.Obj")
local Map = require("core.Map")
local BufferExcel = require("excel.Buffer").Buff
local BufferCmdExcel = require("excel.Buffer").BuffCmd
local BufferNotify = require("buffer.Notify")
local Status = require("scene.Status")
local Conditions = require("skill.Conditions")
local Cmds = require("buffer.Cmds")
local ExcelMonster = require("excel.Monster")
local RoleFFI = require("role.RoleFFI")

list = list or {}
doCalcList = doCalcList or {}
changeList = changeList or {}


--申请一个新buf结构
function newBuf(obj)
    local bufList, len = Obj.getBuf(obj)
    local buf
    if obj.obj_type == Obj.TYPE_HUMAN then
        if len >= 32 then
            return
        end
        buf = bufList[len]
        RoleFFI.memset_zero(buf, 'struct buffer_record')
    else
        buf = {}
        bufList[len] = buf
    end
    Obj.setBufLen(obj, len + 1)
    return buf
end

function freeBuf(obj,buf)
    local bufList, len = Obj.getBuf(obj)
    for i=0, len-1 do
        if bufList[i].id == buf.id and bufList[i].startTime == buf.startTime then
            if obj.obj_type == Obj.TYPE_HUMAN then
                RoleFFI.copy_array_element(bufList, i, len-1, 'struct buffer_record')
            else
                bufList[i] = bufList[len-1]
                bufList[len-1] = nil
            end
            Obj.setBufLen(obj, len-1)
            return
        end
    end
end


function init(obj, login)
    obj.bufChange = 0
    obj.bufChangeSend = 0
    obj.bufAttr = {}
    local bufList, bufLen = Obj.getBuf(obj)
    for i=bufLen -1, 0,-1 do
        local buf = bufList[i]
        if buf then
          local config = BufferExcel[buf.id]
          if not config or (login and config.destroyNoSave == 1) then
            freeBuf(obj, buf)
          else
            if buf.sendUID == -1 then	--自己
                buf.sendID = obj.id
                buf.sendUID = obj.uid
            end
          end
          refreshView(obj,buf)
        end
    end
    bufList, bufLen = Obj.getBuf(obj)
    if bufLen>0 and obj.id then
        list[obj.id] = obj.uid
    end
end

function humanDestroy(obj)
    local objID = obj.id
    list[objID] = nil
    local bufList, len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if config.destroyNoSave == 1 then
            freeBuf(obj,buf)
        else
            local isSelf = obj.objID==buf.sendID
            buf.sendID = 0
            buf.sendUID = isSelf and -1 or 0	--自己加自己
        end
    end
end

function destroy(obj)
    local objID = obj.id
    list[objID] = nil
    removeAll(obj)
end

function removeAll(obj)
    local bufList, len = Obj.getBuf(obj)
    if obj.obj_type == Obj.TYPE_HUMAN then
        Obj.setBufLen(obj,0)
        return
    end
    for i = 0, len -1 do
        bufList[i] = nil
    end
    Obj.setBufLen(obj,0)
end

function onDie(obj)
    local isChange,isCalc
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        if buf then
          local config = BufferExcel[buf.id]
          if config.dieSave == 0 then
            local cmdConfig = BufferCmdExcel[config.cmd]
            remove(obj,buf,true)
            isChange = true
            if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                isCalc = true
            end
          end
        end
    end
    if isChange then
        onChange(obj,isCalc)
    end
end

function add(id,obj,send,skillLevel,tx,ty)
    local config = BufferExcel[id]
    if not obj or not send then
        return
    end
    if send and send.obj_type ~= Obj.TYPE_PET then        
        send = Obj.getOwner(send) or send
    end
    if not config then
        return
        --   assert(nil, id)
    end

    if not Conditions.canAttack(obj) or Cmds.passive.immunityBuf(obj,config,config.cmd) or Cmds.passive.immunityallBuf(obj, config) then --免疫作用
        return
    end

    local bufList, bufLen = Obj.getBuf(obj)
    if bufLen >=32 then return end	--大于32个BUF
    local buf
    if config.isExcludeGroup ==1 and config.group >0 then	--是否同组互斥
        if config.timeCanAppend==1 then	-- 如果时间叠加
            clearBuffGroup(obj,config.group,true,true,id)
            buf = getBufByID(id,obj)
        else
            clearBuffGroup(obj,config.group,true,true)
        end

    elseif config.isExclude==1 then	-- 是否互斥
        removeID(id,obj,true)
    elseif id >= 210 and id <= 212 then
        buf = getBuf(id,obj)
        if not buf then
            clearInvalidSendBuf(id,obj)
        end
    else
        local owner = Obj.getOwner(send)
        if owner then
            buf = getBufByOwner(id,obj,owner)
        else
            buf = getBuf(id,obj,send)
            if not buf then
                clearInvalidSendBuf(id,obj)
            end
        end
    end

    if buf then												-- BUF 已经存在
        if buf.count < config.appendMax then				-- 叠加次数
            buf.count = buf.count+1
            if config.timeCanAppend==1 then					-- 时间可叠加
                buf.time = buf.time + getConfigTimeFix(obj, config)
            end
        end

        if config.noResetTime==0 then	-- 重置时间
            buf.startTime = Timer.now
        end

    else
        buf = newBuf(obj)
        if not buf then
            return
        end
        local now = Timer.now
        buf.id = id
        buf.count = config.count
        buf.time = getConfigTimeFix(obj, config)
        buf.lastTime = now
        buf.startTime = now
    end

    obj.bufAttr = obj.bufAttr or {}

    if Conditions.canAttack(send) then
        buf.sendID = send.id
        buf.sendUID = send.uid
    else
        send = Obj.getOwner(send) or send
        buf.sendID = send.id
        buf.sendUID = send.uid
    end

    buf.skillLevel = skillLevel or 0
    buf.tx = tx or 0
    buf.ty = ty or 0
    buf.firstRun = config.firstRun==1 and 1 or 0

    list[obj.id] = obj.uid

    Cmds.onAdd(obj,buf,config)
    obj.bufChange = obj.bufChange or 0
    obj.bufChange = obj.bufChange + 1
    local cmdConfig = BufferCmdExcel[config.cmd]
    onChange(obj, cmdConfig and cmdConfig.isCalc==1)
end

function getSender(buf)
    return Obj.getObj(buf.sendID,buf.sendUID)
end

function remove(obj,buf,flag,isTimeOver)
    obj.bufChange = obj.bufChange or 0
    obj.bufChange = obj.bufChange + 1
    local config = BufferExcel[buf.id]
    if not isTimeOver then
        onStopCmd(obj,buf,config)
    end

    if not flag then
        local cmdConfig = BufferCmdExcel[config.cmd]
        onChange(obj, cmdConfig and cmdConfig.isCalc==1)
    end
    Cmds.onRemove(obj,buf)

    freeBuf(obj, buf)
    if config.stopStatus==1 then
        Status.doHumanControlStatusChange(obj, Status.HUMAN_STATUS_NORMAL)
    end
end

-- 删除BUFID
function removeID(id,obj,noSend)
    local isChange,isCalc
    local bufList, len = Obj.getBuf(obj)
    for i=len-1,0, -1 do
        local buf = bufList[i]
        if buf.id == id then
            local config = BufferExcel[buf.id]
            local cmdConfig = BufferCmdExcel[config.cmd]

            remove(obj,buf,true)
            isChange = true
            if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                isCalc = true
            end
        end
    end
    if not isChange or noSend then return end
    onChange(obj, isCalc)
end

-- 删除BUF 作用
function removeCmd(obj,cmd)
    local isChange,isCalc
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if not config then
            assert(nil, buf.id)
        end
        if config.cmd == cmd then
            local cmdConfig = BufferCmdExcel[cmd]

            remove(obj,buf,true)
            isChange = true
            if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                isCalc = true
            end
        end
    end
    if not isChange then return end
    onChange(obj,isCalc)
end

function hasCmd(obj,cmd,isGood)
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if config.cmd == cmd and config.isGood == isGood then
            return true
        end
    end
    return false
end

function hasGroup(obj,groupID, groupID2, groupID3)
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if config.group == groupID or config.group == groupID2 or config.group == groupID3 then
            return true
        end
    end
    return false
end

function hasBufIDCount(obj,bufferID,value,max)
    local maxBuf
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        if buf.id == bufferID then
            if not maxBuf or buf.count>maxBuf.count then
                maxBuf = buf
            end
        end
    end
    return maxBuf and maxBuf.count>=value and maxBuf.count<=max
end

function hasBuf(obj,bufferID)
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        if buf.id == bufferID then
            return true
        end
    end
    return false
end

-- [增加Buff叠加次数]
function addBufCount(obj,bufferID,num)
    local bufList,len= Obj.getBuf(obj)
    local isChange,isCalc
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if buf.id == bufferID then
            buf.count = math.min(buf.count + num,config.appendMax)

            local cmdConfig = BufferCmdExcel[config.cmd]
            isChange = true
            if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                isCalc = true
            end
        end
    end
    if not isChange then return end
    onChange(obj,isCalc)
end

-- [减少Buff叠加次数]
function delBufCount(obj,bufferID,num)
    local bufList,len = Obj.getBuf(obj)
    local isChange,isCalc
    for i=len-1,0,-1 do
        local buf = bufList[i]
        if buf.id == bufferID then
            local config = BufferExcel[buf.id]
            if buf.count - num <=0 then
                local cmdConfig = BufferCmdExcel[config.cmd]
                remove(obj,buf,true)
               

                if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                    isCalc = true
                end
            else
                buf.count = buf.count - num
            end
            isChange = true
        end
    end
    if not isChange then return end
    onChange(obj,isCalc)
end

-- 以下函数为外部调用清除BUF, 触发移除时作用
function clearBuffUtility(obj,cmd,isGood,num)
    if num<1 then return end
    local isChange,isCalc
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if config.cmd == cmd and config.isClear == 1 and config.isGood == isGood then
            local cmdConfig = BufferCmdExcel[cmd]

            remove(obj,buf,true)
            isChange = true

            if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                isCalc = true
            end

            num = num-1
            if num <=0 then
                break
            end
        end
    end
    if not isChange then return end
    onChange(obj,isCalc)
end

function clearBuf(obj,isGood,num)
    if num<1 then return end
    local isChange,isCalc
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if config.isClear == 1 and  config.isGood == isGood then
            local cmdConfig = BufferCmdExcel[config.cmd]

            remove(obj,buf,true)
            isChange = true

            if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                isCalc = true
            end

            num = num-1
            if num <=0 then
                break
            end
        end
    end
    if not isChange then return end
    onChange(obj,isCalc)
end

function clearSkillBuf(obj)
    local isChange,isCalc
    local bufList,len= Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if config.isSkillBuf == 1 then
            local cmdConfig = BufferCmdExcel[config.cmd]

            remove(obj,buf,true)
            isChange = true

            if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                isCalc = true
            end
        end
    end
    if not isChange then return end
    onChange(obj,isCalc)
end

function clearBuffGroup(obj,groupID,noSend,must,exceptBufID)
    local isChange,isCalc
    local bufList, len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        if (config.isClear == 1 or must) and config.group == groupID and buf.id ~= exceptBufID then
            local cmdConfig = BufferCmdExcel[config.cmd]

            remove(obj,buf,true)
            isChange = true

            if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                isCalc = true
            end
        end
    end
    if not isChange or noSend then return end
    onChange(obj, isCalc)
end

function clearAllBuff(obj)
    local isChange,isCalc
    local bufList, len= Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        local cmdConfig = BufferCmdExcel[config.cmd]
        isChange = true
        if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
            isCalc = true
            break
        end
    end
    removeAll(obj)
    if not isChange then return end
    onChange(obj, isCalc)
end


-- 获取BUF
function getBuf(id,obj,send)
    local bufList, len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        if buf.id == id and (not send or getSender(buf) == send) then
            return buf
        end
    end
end

function getBufByID(id,obj)
    local bufList, len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        if buf.id == id then
            return buf
        end
    end
end

function getBufByOwner(id,obj,owner)
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local send = getSender(buf)
        if buf.id == id and send and (owner==send or owner == Obj.getOwner(send)) then
            return buf
        end
    end
end

function clearInvalidSendBuf(id,obj)	--清除无效的攻击者 BUF
    local bufList, len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        if buf.id == id and not getSender(buf) then
            remove(obj,buf,true)
        end
    end
end

function doCmd(calls,obj,buf,arg,cmd)
    local config = BufferExcel[buf.id]
    cmd = cmd or config.cmd
    local call = calls[cmd]
    if not call then return end
    
    local cmdConfig = BufferCmdExcel[cmd]
    call(obj,buf,config,cmdConfig,getAppendArg(buf,config,cmdConfig,arg))
end

function getAppendArg(buf,config,cmdConfig,arg)

    arg = arg or config.arg
    local appendArg = cmdConfig.appendArg
    if config.valCanAppend == 1 then
        return  appendArg[1]==1 and arg[1]*buf.count or arg[1] ,
        appendArg[2]==1 and arg[2]*buf.count or arg[2] ,
        appendArg[3]==1 and arg[3]*buf.count or arg[3] ,
        appendArg[4]==1 and arg[4]*buf.count or arg[4] ,
        appendArg[5]==1 and arg[5]*buf.count or arg[5],
        appendArg[6]==1 and arg[6]*buf.count or arg[6]
    else
        return arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]
    end
end

function onChange(obj,isCalc)
    changeList[obj.id] = obj.uid
    if isCalc then
        doCalcList[obj.id] = obj.uid
    end
end

function getConfigTimeFix(o, cf)
    if cf.cmd == "giddy" and o.monster_id then
        local monster_type = ExcelMonster.monster[o.monster_id].monster_type
        return ExcelMonster.monster_type[monster_type].xuan_yun_fix * cf.time * 1000
    elseif o.monster_id and cf.cmd == "fear" then
        local monster_type = ExcelMonster.monster[o.monster_id].monster_type
        return ExcelMonster.monster_type[monster_type].kong_ju_fix * cf.time * 1000 
    end
    return cf.time * 1000
end

function getBufferColor(obj)
    return obj.bufAttr.color or 0
end

function getBufferScale(obj)
    return obj.bufAttr.scale or 0
end

function getBodyInfo(obj)
    local t = obj.bufAttr.copyBody
    if t then
        return t[1], t[2], t[3], t[4], t[5], t[6], t[7],t[8]
    end
    
    t = obj.bufAttr.body    
    if t == obj.bufAttr.body then    
        local config = BufferExcel[t]
        if config then
            return config.arg[1], config.arg[2],config.arg[3], config.arg[4], config.arg[5],config.arg[6], config.arg[7],config.arg[8],config.arg[9],config.arg[10],config.arg[11]
        end
    end    
end


function onItemUse(obj)
    removeCmd(obj,"tempInvincible")	-- 删除临时无敌BUF
end

-- 删除阻断BUF
STOP_TYPE_SKILL_STOP = 0	--主动停止技能
STOP_TYPE_SKILL_USE = 1	--使用技能
STOP_TYPE_HIT = 2			--击中
STOP_TYPE_GIDDY = 3		--晕眩
STOP_TYPE_NO_SKILL = 4	--沉默
STOP_TYPE_MOVE = 5		--移动
STOP_TYPE_STATUS = 6	--生活技能
STOP_TYPE_HIT_HUMAN = 7	--被击中（人物攻击）
STOP_TYPE_HIT_TARGET = 8  --击中目标

function delStop(obj,type,noSend)
    local isChange,isCalc
    local bufList,len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        if buf then
          local config = BufferExcel[buf.id]
          for _,stopType in ipairs(config.stop) do
            if stopType == type then
                local cmdConfig = BufferCmdExcel[config.cmd]

                remove(obj,buf,true)
                isChange = true

                if not isCalc and cmdConfig and cmdConfig.isCalc == 1 then
                    isCalc = true
                end

                break
            end
          end
        end
    end
    if not isChange or noSend  then return end
    onChange(obj, isCalc)
end

function onSkillStop(obj)			--主动停止技能
    delStop(obj,STOP_TYPE_SKILL_STOP)
end

function onHit(obj, target) --击中
    delStop(obj, STOP_TYPE_HIT_TARGET)
end

function onBeHit(attacker,obj)				--被击中
    delStop(obj,STOP_TYPE_HIT)
    if attacker.obj_type == Obj.TYPE_HUMAN then	-- 被人物击中
        delStop(obj,STOP_TYPE_HIT_HUMAN)
    end
end

function onSkill(obj)				--使用技能
    delStop(obj,STOP_TYPE_SKILL_USE)
    removeCmd(obj,"tempInvincible")	-- 删除临时无敌BUF
    --removeCmd(obj,"hide")			-- 隐身
end

function onMove(obj)			--移动
    delStop(obj,STOP_TYPE_MOVE)
end

function canFindAttack(recv)			-- 怪物寻找目标
    if recv.status==Status.HUMAN_STATUS_HIDE then return end
    return true
end

-- 计算BUFFER属性
rateCalcsList = rateCalcsList or {}
calcsList = calcsList or {}
combatCalcAttr = combatCalcAttr or {
    baojiRate		=true,
    makeShanghai	=true,
    makeShanghaiRate=true,
    hitRate			=true,
    shanbiRate		=true,
    recvShanghai	=true,
    recvShanghaiRate=true,
    renxingRate		=true,
    defCtRate		=true,
    defCt			=true,
    xuanyunRate = true,
    kangyunRate = true,
    luomaRate = true,
    qishuRate = true,
}

function calcsInit(obj)


    for k in pairs(rateCalcsList)  do
        rateCalcsList[k] = nil
    end

    for k in pairs(calcsList) do
        calcsList[k] = nil
    end

    local rateCalcs = Cmds.rateCalcs
    local calcs = Cmds.calcs

    obj.bufAttr = obj.bufAttr or {}
    for k in pairs(obj.bufAttr) do
        obj.bufAttr[k] = combatCalcAttr[k] and 0 or nil	--战斗属性默认为0
    end

    local bufList, len = Obj.getBuf(obj)
    for i=len-1,0,-1 do
        local buf = bufList[i]
        local config = BufferExcel[buf.id]
        local cmd = config.cmd
        if config then
            if Cmds[cmd] then
                doCmd(Cmds,obj,buf)
                if not rateCalcsList[cmd] and rateCalcs[cmd] then
                    rateCalcsList[cmd] = true
                end
                if not calcsList[cmd] and calcs[cmd] then
                    calcsList[cmd] = true
                end
            end
            refreshView(obj,buf)
        end
    end
end



function refreshRate(obj)
    local rateCalcs = Cmds.rateCalcs
    for cmd in pairs(rateCalcsList)  do
        rateCalcs[cmd](obj.attr,obj.bufAttr,obj)
    end
end

function refresh(obj)
    local calcs = Cmds.calcs
    for cmd in pairs(calcsList)  do
        calcs[cmd](obj.attr,obj.bufAttr,obj)
    end
end

function refreshView(obj,buf)
    local bufAttr = obj.bufAttr
    local config = BufferExcel[buf.id]
    if not config then return end
    if bufAttr.stopStatus ~= config.stopStatus and not bufAttr.stopStatus and config.stopStatus~= 0 then
        bufAttr.stopStatus = config.stopStatus
    end
    if bufAttr.color ~= config.color and not bufAttr.color and config.color~= 0 then
        bufAttr.color = config.color
    end
    
    local scale = config.scale * buf.count
    if bufAttr.scale ~= scale and not bufAttr.scale and scale~= 0 then
        bufAttr.scale = scale
    end
    if not bufAttr.typeArgs and Cmds.setTypeArgs[config.cmd] then
        bufAttr.typeArgs = true
    end
end

function onLoop()
    local loopCall  = Cmds.loopCall
    local now		= Timer.now
    for objID,uid in pairs(list) do
        local obj = Obj.getObj(objID,uid)
        if obj then
            local mapID = Map.scene_id_to_map_id[obj.scene_id]
            local bufList, len = Obj.getBuf(obj)
            if len > 0 then
                for i=len-1,0,-1 do
                    local buf = bufList[i]
                    if buf then
                      local config = BufferExcel[buf.id]
                      local sender = Obj.getObj(buf.sendID, buf.sendUID)
                      if not config or (next(config.inMap) and not config.inMap[mapID] ) or (obj.monster_id and (not sender or sender.obj_type == Obj.TYPE_HUMAN and (sender.db.hp < 1 or sender.scene_id ~= obj.scene_id))) then	--找不到配置 或者 此地图不生效 或者是加在怪物身上的BUF攻击者不存在(死亡、不在同一场景)
                        remove(obj,buf,nil,true)
                      else
                        if buf.firstRun == 1 or now - buf.lastTime >= config.speed*1000 then
                            buf.firstRun = 0
                            buf.lastTime  = now
                            doCmd(loopCall,obj,buf)
                        end
                        if buf.time>0 and now - buf.startTime >= buf.time then
                            onTimeOverCmd(obj,buf,config)				--Buff 结束时作用
                            remove(obj,buf,nil,true)
                        end
                      end
                    end
                end
            else
                list[objID] = nil
            end
        else
            list[objID] = nil
        end
    end
end



function onTimer()
    onLoop()
    for id,uid in pairs(changeList) do
        changeList[id] = nil
        local isCalc = doCalcList[id]
        doCalcList[id] = nil

        local obj = Obj.getObj(id,uid)
        if obj then
            if isCalc then
                Obj.doCalc(obj)
            else
                calcsInit(obj)
            end
            BufferNotify.sendBufferList(obj)
            Status.sendViewStatus(obj,true)
        end
    end
end

function onTimeOverCmd(obj,buf,config)
    if #config.timeOverCmd<1 then return end
    for k in pairs(obj.bufAttr) do
        obj.bufAttr[k] = combatCalcAttr[k] and 0 or nil
    end
    doCmd(Cmds,obj,buf,config.timeOverArg,config.timeOverCmd)
    doCmd(Cmds.loopCall,obj,buf,config.timeOverArg,config.timeOverCmd)
end

function onStopCmd(obj,buf,config)
    if #config.stopCmd<1 then return end
    for k in pairs(obj.bufAttr) do
        obj.bufAttr[k] = combatCalcAttr[k] and 0 or nil
    end
    doCmd(Cmds,obj,buf,config.stopArg,config.stopCmd)
    doCmd(Cmds.loopCall,obj,buf,config.stopArg,config.stopCmd)
end


